﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.IO.IsolatedStorage;
using System.Diagnostics;

namespace ControlHost
{
    public partial class MousePage : PhoneApplicationPage
    {
        IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;

        const int MOUSE_DATA_LEN = 16;
        const int MOUSE_DOWN = 1;
        const int MOUSE_MOVE = 2;
        const int MOUSE_UP = 3;

        //public TcpSocket tcpSock;
        public UdpSocket udpSock;
        public string strHost;
        public int nPort;
        public byte[] data;
        int last_x = 0, last_y = 0;
        int m_nTapState;
        int m_nTapTickCount;
        TouchPoint[] m_touchPointBuf;
        int m_nSendIndex;
        const int MAX_POINT_BUF_NUM = 5;

        public MousePage()
        {
            InitializeComponent();
            InitSettings();

            m_nTapState = 0;
            m_nTapTickCount = 0;
            data = new byte[64];
            m_touchPointBuf = new TouchPoint[MAX_POINT_BUF_NUM];
            m_nSendIndex = 0;
            Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);
        }

        private void InitSettings()
        {
            if (settings.Contains("Host"))
            {
                strHost = (string)settings["Host"];
            }
            else
            {
                strHost = "192.168.1.102";
                settings.Add("Host", strHost);
            }

            if (settings.Contains("Port"))
            {
                nPort = (int)settings["Port"];
            }
            else
            {
                nPort = 11000;
                settings.Add("Port", nPort);
            }

            (Application.Current as App).strHost = strHost;
            (Application.Current as App).nPort = nPort;
        }
        
        void Touch_FrameReported(object sender, TouchFrameEventArgs e)
        {
            var primaryPoint = e.GetPrimaryTouchPoint(null);

            if (NavigationService.CurrentSource.ToString() != "/MousePage.xaml")
                return;

            ////////////////////
            TouchPointCollection touchPoints = e.GetTouchPoints(null);
            //Debug.WriteLine("count is {0}",touchPoints.Count);
            foreach (TouchPoint touchPoint in touchPoints)
            {
                //Debug.WriteLine("action={0} x={1}, y={2}", touchPoint.Action, touchPoint.Position.X, touchPoint.Position.Y);

                if ((touchPoint.Position.X >= btnLeft.Margin.Left) && (touchPoint.Position.X <= btnLeft.Margin.Left + btnLeft.Width)
                    && (touchPoint.Position.Y >= btnLeft.Margin.Top) && (touchPoint.Position.Y <= btnLeft.Margin.Top + btnLeft.Height + 26)
                    )
                {
                    if (touchPoint.Action == TouchAction.Down)
                    {
                        btnLeft.Background = new SolidColorBrush(Colors.White);
                        sendLeftCoord(MOUSE_DOWN, 0, 0);
                    }
                    else if (touchPoint.Action == TouchAction.Up)
                    {
                        sendLeftCoord(MOUSE_UP, 0, 0);
                        btnLeft.Background = new SolidColorBrush(Colors.Black);
                    }
                }
                if ((touchPoint.Position.X >= rectMouseArea.Margin.Left) && (touchPoint.Position.X <= rectMouseArea.Margin.Left + rectMouseArea.Width)
                    && (touchPoint.Position.Y >= rectMouseArea.Margin.Top) && (touchPoint.Position.Y <= rectMouseArea.Margin.Top + rectMouseArea.Height)
                    )
                {
                    if (m_nSendIndex == 0)
                    {
                        m_touchPointBuf[m_nSendIndex] = touchPoint;
                        m_nSendIndex++;
                    }
                    else if (m_nSendIndex < MAX_POINT_BUF_NUM)
                    {
                        if (touchPoint.Action == TouchAction.Up)
                        {
                            sendLeftCoord(MOUSE_DOWN, 0, 0);
                            sendLeftCoord(MOUSE_UP, 0, 0);
                            m_nTapState = 1;
                            m_nTapTickCount = Environment.TickCount;
                        }
                        else
                        {
                            m_touchPointBuf[m_nSendIndex] = touchPoint;
                        }
                        m_nSendIndex++;
                    }
                    else if (m_nSendIndex == MAX_POINT_BUF_NUM)
                    {
                        if (m_nTapState == 1)
                        {
                            Debug.WriteLine(Environment.TickCount - m_nTapTickCount);
                            if (Environment.TickCount - m_nTapTickCount < 300)
                            {
                                sendLeftCoord(MOUSE_DOWN, 0, 0);
                                m_nTapState = 2;
                            }
                            else
                            {
                                m_nTapState = 0;
                            }
                        }
                        for (int i = 0; i < MAX_POINT_BUF_NUM; i++)
                        {
                            sendCoord(m_touchPointBuf[i]);
                        }
                        sendCoord(touchPoint);
                        m_nSendIndex++;
                    }
                    else
                    {
                        sendCoord(touchPoint);

                    }
                    if (touchPoint.Action == TouchAction.Up)
                    {
                        m_nSendIndex = 0;
                        if (m_nTapState == 2)
                        {
                            sendLeftCoord(MOUSE_UP, 0, 0);
                            m_nTapState = 0;
                        }
                    }
                }
            }

            ///////////////////////////////
            /*
            if (primaryPoint != null)
            {
                sendCoord(primaryPoint);
            }
             * */

        }

        void sendCoord(TouchPoint touchPoint)
        {
            int s = 0, x = 0, y = 0;
            int temp_x = 0, temp_y = 0;

            x = (int)touchPoint.Position.X;
            y = (int)touchPoint.Position.Y;

            if (touchPoint.Action == TouchAction.Down)
            {
                s = MOUSE_MOVE;
                temp_x = 0;
                temp_y = 0;
            }
            else if (touchPoint.Action == TouchAction.Move)
            {
                s = MOUSE_MOVE;
                temp_x = x - last_x;
                temp_y = y - last_y;
            }
            else
            {
                s = MOUSE_MOVE;
                temp_x = x - last_x;
                temp_y = y - last_y;
            }

            sendLeftCoord(s, temp_x, temp_y);

            last_x = x;
            last_y = y;
        }

        void sendLeftCoord(int s, int x, int y)
        {
            data[0] = 0xfe;
            data[1] = (byte)MOUSE_DATA_LEN;
            //data[2] = 0x00;
            data[3] = 0x01; //input
            data[4] = 0x01; //mouse
            data[5] = 0x01; //left button
            data[6] = (byte)s;
            data[7] = (byte)((x >> 8) & 0xff);
            data[8] = (byte)(x & 0xff);
            data[9] = (byte)((y >> 8) & 0xff);
            data[10] = (byte)(y & 0xff);
            data[2] = countChecksum(data, 3, data[1]);

            //tcpSock.Send(data, data[1]);
            udpSock.Send(strHost, nPort, data, data[1]);
        }

        void sendRightCoord(int s, int x, int y)
        {
            data[0] = 0xfe;
            data[1] = (byte)MOUSE_DATA_LEN;
            //data[2] = 0x00;
            data[3] = 0x01; //input
            data[4] = 0x01; //mouse
            data[5] = 0x02; //right
            data[6] = (byte)s;
            data[7] = (byte)((x >> 8) & 0xff);
            data[8] = (byte)(x & 0xff);
            data[9] = (byte)((y >> 8) & 0xff);
            data[10] = (byte)(y & 0xff);
            data[2] = countChecksum(data, 3, data[1]);

            //tcpSock.Send(data, data[1]);
            udpSock.Send(strHost, nPort, data, data[1]);
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            //tcpSock = (Application.Current as App).tcpSock;
            udpSock = (Application.Current as App).udpSock;
            strHost = (Application.Current as App).strHost;
            nPort = (Application.Current as App).nPort;
            //Debug.WriteLine("{0}, {1}", strHost, nPort);

            base.OnNavigatedTo(e);
        }

        private void btnLeft_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            //Debug.WriteLine("btnLeft_ManipulationStarted");

            //left button down
            //sendLeftCoord(MOUSE_DOWN, 0, 0);

            //btnRight.Background = new SolidColorBrush(Colors.Blue);

        }

        private void btnLeft_Click(object sender, RoutedEventArgs e)
        {
            //Debug.WriteLine("btnLef_Click");

            //left button up
            //sendLeftCoord(MOUSE_UP, 0, 0);

            //btnRight.Background = new SolidColorBrush(Colors.Black);
        }

        private void btnRight_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
        {
            //right button down
            sendRightCoord(MOUSE_DOWN, 0, 0);
        }

        private void btnRight_Click(object sender, RoutedEventArgs e)
        {
            //right button up
            sendRightCoord(MOUSE_UP, 0, 0);
        }

        public byte countChecksum(byte[] data, int start, int length)
        {
            int temp;
            byte byteChecksum;

            temp = 0;
            for (int i = start; i < length; i++)
                temp = (temp + data[i]) & 0xff;
            byteChecksum = Convert.ToByte(temp);

            return byteChecksum;
        }
    }
}